#include "viml/builtin_path.h"
#include "viml/value.h"
#include <filesystem>
#include <stdexcept>
#include <string>

namespace fs = std::filesystem;

namespace viml {

// ========================================
// 路径处理函数实现
// ========================================

Value path_join_builtin(const std::vector<Value>& args) {
    if (args.empty()) {
        throw std::runtime_error("path_join() requires at least 1 argument");
    }
    
    fs::path result;
    
    for (const auto& arg : args) {
        if (!arg.is_string()) {
            throw std::runtime_error("path_join() all arguments must be strings");
        }
        
        if (result.empty()) {
            result = fs::path(arg.as_string());
        } else {
            result /= arg.as_string();
        }
    }
    
    return Value::string(result.string());
}

Value path_normalize_builtin(const std::vector<Value>& args) {
    if (args.size() != 1) {
        throw std::runtime_error("path_normalize() requires exactly 1 argument");
    }
    
    if (!args[0].is_string()) {
        throw std::runtime_error("path_normalize() argument must be a string");
    }
    
    try {
        fs::path p(args[0].as_string());
        fs::path normalized = p.lexically_normal();
        return Value::string(normalized.string());
    } catch (const std::exception& e) {
        throw std::runtime_error("path_normalize() failed: " + std::string(e.what()));
    }
}

Value path_absolute_builtin(const std::vector<Value>& args) {
    if (args.size() != 1) {
        throw std::runtime_error("path_absolute() requires exactly 1 argument");
    }
    
    if (!args[0].is_string()) {
        throw std::runtime_error("path_absolute() argument must be a string");
    }
    
    try {
        fs::path p(args[0].as_string());
        fs::path absolute = fs::absolute(p);
        return Value::string(absolute.string());
    } catch (const std::exception& e) {
        throw std::runtime_error("path_absolute() failed: " + std::string(e.what()));
    }
}

Value path_dirname_builtin(const std::vector<Value>& args) {
    if (args.size() != 1) {
        throw std::runtime_error("path_dirname() requires exactly 1 argument");
    }
    
    if (!args[0].is_string()) {
        throw std::runtime_error("path_dirname() argument must be a string");
    }
    
    try {
        fs::path p(args[0].as_string());
        return Value::string(p.parent_path().string());
    } catch (const std::exception& e) {
        throw std::runtime_error("path_dirname() failed: " + std::string(e.what()));
    }
}

Value path_basename_builtin(const std::vector<Value>& args) {
    if (args.size() != 1) {
        throw std::runtime_error("path_basename() requires exactly 1 argument");
    }
    
    if (!args[0].is_string()) {
        throw std::runtime_error("path_basename() argument must be a string");
    }
    
    try {
        fs::path p(args[0].as_string());
        return Value::string(p.filename().string());
    } catch (const std::exception& e) {
        throw std::runtime_error("path_basename() failed: " + std::string(e.what()));
    }
}

Value path_extension_builtin(const std::vector<Value>& args) {
    if (args.size() != 1) {
        throw std::runtime_error("path_extension() requires exactly 1 argument");
    }
    
    if (!args[0].is_string()) {
        throw std::runtime_error("path_extension() argument must be a string");
    }
    
    try {
        fs::path p(args[0].as_string());
        return Value::string(p.extension().string());
    } catch (const std::exception& e) {
        throw std::runtime_error("path_extension() failed: " + std::string(e.what()));
    }
}

Value path_separator_builtin(const std::vector<Value>& args) {
    if (args.size() != 0) {
        throw std::runtime_error("path_separator() requires no arguments");
    }
    
#ifdef _WIN32
    return Value::string("\\");
#else
    return Value::string("/");
#endif
}

} // namespace viml
